package id.co.shuba.spamobile.activities;

import java.io.File;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;

import com.actionbarsherlock.app.SherlockActivity;
import com.actionbarsherlock.app.SherlockListActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;

import id.co.shuba.spamobile.App;
import id.co.shuba.spamobile.Configs;
import id.co.shuba.spamobile.CustomSessionApplication;
import id.co.shuba.spamobile.LogoutReceiver;
import id.co.shuba.spamobile.R;
import id.co.shuba.spamobile.Sessions;
import id.co.shuba.spamobile.R.layout;
import id.co.shuba.spamobile.R.menu;
import id.co.shuba.spamobile.data.DatabaseHandler;
import id.co.shuba.spamobile.data.StandardDB;
import id.co.shuba.spamobile.model.UserInfo;
import id.co.shuba.spamobile.services.WebServiceHelper;
import id.co.shuba.spamobile.task.AsyncTaskResult;
import id.co.shuba.spamobile.task.BaseProgressTask;
import id.co.shuba.spamobile.task.DownloadAreaTask;
import id.co.shuba.spamobile.task.DownloadChannelTask;
import id.co.shuba.spamobile.task.DownloadExternalMappingTask;
import id.co.shuba.spamobile.task.DownloadFlagFreezeTask;
import id.co.shuba.spamobile.task.DownloadHolidayTask;
import id.co.shuba.spamobile.task.DownloadMaintenanceVisitTask;
import id.co.shuba.spamobile.task.DownloadProspectRefferalTask;
import id.co.shuba.spamobile.task.DownloadProspectUpdateTask;
import id.co.shuba.spamobile.task.DownloadStandardTask;
import id.co.shuba.spamobile.task.DownloadProductTask;
import id.co.shuba.spamobile.task.DownloadProspectByDateTask;
import id.co.shuba.spamobile.task.IDatabaseSync;
import id.co.shuba.spamobile.task.INotify;
import id.co.shuba.spamobile.task.MockProgressTask;
import id.co.shuba.spamobile.task.TestDownloadTask;
import id.co.shuba.spamobile.task.UploadMaintenanceVisitTask;
import id.co.shuba.spamobile.task.UploadProspectTask;
import id.co.shuba.spamobile.widget.ProgressAdapter;
import android.os.AsyncTask;
import android.os.AsyncTask.Status;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import android.view.ContextThemeWrapper;

public class DownloadActivity extends SherlockListActivity implements INotify {
	public static final int DOWNLOAD_MASTER = 1;
	public static final int DOWNLOAD_PROSPECT_BY_DATE = 2;
	public static final int UPLOAD_ALL = 3;

	public static final String PARAMETER_EXIT_WHEN_DONE = "exitWhenDone";
	public static final String PARAMETER_DOWNLOAD_UPDATE = "downloadUpdate";
	public static final String PARAMETER_AUTO_START = "autoStart";
	public static final String PARAMETER_OPTION = "option";
	public static final String PARAMETER_CANCELABLE = "cancelable";
	public static final String PARAMETER_GO_TO_MAIN_WHEN_DONE = "goToMainWhenDone";
	public static final String PARAMETER_GO_TO_DOWNLOAD_OFFLINE_WHEN_DONE = "goToDownloadOfflineWhenDone";
	public static final String PARAMETER_GO_TO_LOGIN_WHEN_DONE = "goToLoginWhenDone";

	public static final String PARAMETER_PROSPECT_START_DATE = "startDate";
	public static final String PARAMETER_PROSPECT_END_DATE = "endDate";
	public static final String PARAMETER_FORCE_DOWNLOAD = "forceDownload";

	private int _imgRes;
	private String _activityCaption;
	private String _menuCaption;
	private boolean _autoStart;
	private boolean _exitWhenDone;
	private int _option;
	private boolean _cancelable;
	private boolean _goToMainWhenDone;
	private boolean _goToDownloadOfflineWhenDone;
	private boolean _goToLoginWhenDone;
	private boolean _isDownloadUpdate;

	private ArrayList<BaseProgressTask> _list;
	private DatabaseHandler _handler;
	private WebServiceHelper _ws;
	private SQLiteDatabase _db;
	private MenuItem _btnAction;
	
	//private String[] _errorTask;

	//private boolean _onProgress;
	//private volatile int _countFinished = 0;

	private UserInfo _user;
	private String _imei;

	private String _startDate;
	private String _endDate;
	
	private LogoutReceiver logoutReceiver;
		
	private AtomicInteger _countFinish;		
	private AtomicInteger _countError;
	
	private boolean _forceDownload;

	private ArrayList<BaseProgressTask> createDownloadMasterTaskList() {
		ArrayList<BaseProgressTask> list = new ArrayList<BaseProgressTask>();
		list.add(new DownloadProductTask(_ws, _db, this));
		list.add(new DownloadChannelTask(_ws, _db, this, _forceDownload));		
		list.add(new DownloadStandardTask(_ws, _db, this, _forceDownload));
		list.add(new DownloadAreaTask(_ws, _db, _user.getAoCode(), this, _forceDownload));
		list.add(new DownloadHolidayTask(_ws, _db, this, _forceDownload));
		list.add(new DownloadExternalMappingTask(_ws, _db, this, _forceDownload));
		list.add(new DownloadFlagFreezeTask(_ws, _db, this, _forceDownload));
		list.add(new DownloadMaintenanceVisitTask(_ws, _db, this, _user, _imei));
		
		
		if (_isDownloadUpdate) {
			list.add(new DownloadProspectUpdateTask(_ws, _db, this, _user, _imei));
			list.add(new DownloadProspectRefferalTask(_ws, _db, this, _user, _imei, Configs.getGuFup(this)));
		}

		return list;
	}

	private ArrayList<BaseProgressTask> createDownloadProspectList() {
		ArrayList<BaseProgressTask> list = new ArrayList<BaseProgressTask>();
		list.add(new DownloadProspectByDateTask(_ws, _db, this, _user, _imei,
				_startDate, _endDate));

		return list;
	}

	private ArrayList<BaseProgressTask> createUploadTransactionList() {
		ArrayList<BaseProgressTask> list = new ArrayList<BaseProgressTask>();
		list.add(new UploadMaintenanceVisitTask(_ws, _handler, this, _user,
				_imei));
		list.add(new UploadProspectTask(_ws, _handler, this, _user, _imei));

		return list;
	}
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_download);
		setUpLogoutReceiver();
		
		Intent intent = getIntent();
		initParameter(intent);		
		
		_ws = new WebServiceHelper(this);		
		_user = Sessions.getUser(this);
		_imei = App.getImei(this);

		getSupportActionBar().setTitle(_activityCaption);

		restoreProgress();
	}
	
	private void setUpLogoutReceiver() {
		IntentFilter intentFilter = new IntentFilter();
	    intentFilter.addAction("id.co.shuba.spamobile.ACTION_LOGOUT");
	    logoutReceiver = new LogoutReceiver(this);
	    registerReceiver(logoutReceiver, intentFilter);
	}
		
	@SuppressWarnings("unchecked")
	private void restoreProgress() {
		@SuppressWarnings("deprecation")
		Object obj = getLastNonConfigurationInstance();	

		if (obj != null) {
			Object[] aObj = (Object[]) obj;
			
			_list = (ArrayList<BaseProgressTask>) aObj[0];
			_handler = (DatabaseHandler) aObj[1];
			_db = (SQLiteDatabase) aObj[2];			
			_countFinish = (AtomicInteger) aObj[3];
			_countError = (AtomicInteger) aObj[4];
			
			ProgressAdapter adapter = new ProgressAdapter(this, _list, _imgRes);
			setListAdapter(adapter);
		} else {
			_handler = new DatabaseHandler(this);			
			
			_db = _handler.getWritableDatabase();
			
			if (_autoStart) {
				executeAll();
			} else {
				_list = new ArrayList<BaseProgressTask>();
				_countFinish = new AtomicInteger();
				_countError = new AtomicInteger();

				ProgressAdapter adapter = new ProgressAdapter(this, _list,
						_imgRes);
				setListAdapter(adapter);
			}
		}
	}
	
	private void initParameter(Intent intent) {
		_autoStart = getIntent().getBooleanExtra(PARAMETER_AUTO_START, false);
		_exitWhenDone = getIntent().getBooleanExtra(PARAMETER_EXIT_WHEN_DONE,
				false);
		_option = getIntent().getIntExtra(PARAMETER_OPTION, DOWNLOAD_MASTER);
		_cancelable = getIntent().getBooleanExtra(PARAMETER_CANCELABLE, true);
		_goToMainWhenDone = getIntent().getBooleanExtra(
				PARAMETER_GO_TO_MAIN_WHEN_DONE, false);
		_goToDownloadOfflineWhenDone = getIntent().getBooleanExtra(
				PARAMETER_GO_TO_DOWNLOAD_OFFLINE_WHEN_DONE, false);
		_goToLoginWhenDone = getIntent().getBooleanExtra(
				PARAMETER_GO_TO_LOGIN_WHEN_DONE, false);

		_startDate = getIntent().getStringExtra(PARAMETER_PROSPECT_START_DATE);
		_endDate = getIntent().getStringExtra(PARAMETER_PROSPECT_END_DATE);
		_forceDownload = getIntent().getBooleanExtra(PARAMETER_FORCE_DOWNLOAD, false);
		
		_isDownloadUpdate = getIntent().getBooleanExtra(PARAMETER_DOWNLOAD_UPDATE, false);
		_countFinish = new AtomicInteger();
		_countError = new AtomicInteger();
		switch (_option) {
		case DOWNLOAD_MASTER:
			_imgRes = R.drawable.ic_download;
			_menuCaption = "Download";
			_activityCaption = "Download Master";
			break;
		case DOWNLOAD_PROSPECT_BY_DATE:
			_imgRes = R.drawable.ic_download;
			_menuCaption = "Download";
			_activityCaption = "Download Prospect";
			break;
		case UPLOAD_ALL:
			_imgRes = R.drawable.ic_upload;
			_menuCaption = "Upload";
			_activityCaption = "Upload Transaction";
			break;
		default:
			break;
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getSupportMenuInflater().inflate(R.menu.activity_download, menu);

		_btnAction = menu.findItem(R.id.menu_download);
		_btnAction.setTitle(_menuCaption);
		_btnAction.setEnabled(!_autoStart);

		return true;
	}

	public boolean onOptionsItemSelected(MenuItem item) {
		if (item.getItemId() == R.id.menu_download) {
			_btnAction.setEnabled(false);
			executeAll();
		}

		return super.onOptionsItemSelected(item);
	}

	@SuppressLint("NewApi")
	private void executeAll() {		
		switch (_option) {
		case DOWNLOAD_MASTER:
			_list = createDownloadMasterTaskList();
			break;
		case DOWNLOAD_PROSPECT_BY_DATE:
			_list = createDownloadProspectList();
			break;
		case UPLOAD_ALL:
			_list = createUploadTransactionList();
			break;
		default:
			_list = new ArrayList<BaseProgressTask>();
			break;
		}

		ProgressAdapter adapter = new ProgressAdapter(this, _list, _imgRes);
		setListAdapter(adapter);
		_countFinish.set(0);
		
		for (int i = 0; i < _list.size(); i++) {
			BaseProgressTask task = _list.get(i);
			if (_isDownloadUpdate) {
				task.execute();
			} else if (Build.VERSION.SDK_INT >= 11) {				
				task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
			}
			//if (Build.VERSION.SDK_INT >= 11) {
				//task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
				
			/*} else {
				task.execute();
			}*/						
		}
	}

	@Override
	public Object onRetainNonConfigurationInstance() {
		for (BaseProgressTask task : _list) {
			task.setProgressChangedListener(null);
			task.setStatusListener(null);
		}
		return new Object[] { _list, _handler, _db, _countFinish, _countError };
	}

	@Override
	protected void onDestroy() {		
		closeDB();
		unregisterReceiver(logoutReceiver);
		super.onDestroy();
	}
	
	private void closeDB() {
		if (_exitWhenDone && isAllFinish() && _handler != null)
			_handler.close();
	}	

	@Override
	public void notifyFinish(Exception e) {
		_countFinish.incrementAndGet();
		if (e != null) {
			_countError.incrementAndGet();
		}
		
		if (isAllFinish()) {				
			setAllFinish();
		}	
	}	
		
	public boolean isAllFinish() {			
		int count = _list.size();					
		Log.d("DOWNLOAD", "Finished Download: "+ _countFinish.get() +" of " + count);		
		return count == _countFinish.get();
	}

	private void setAllFinish() {
		boolean error = _countError.get() > 0;
		if (_btnAction != null) {
			if (error) {			
				_btnAction.setTitle("Retry");
			} 
			_btnAction.setEnabled(true);
		} 		
				
		_countFinish.set(_list.size());
		_countError.set(0);
		
		if (_exitWhenDone && !error) {
			if (_goToMainWhenDone) {				
				Intent intent = new Intent(this, MainActivity.class);
				startActivity(intent);
			} else if (_goToDownloadOfflineWhenDone) {
				File file = App.getOfflineUpdatePath("master.spapkg");
				File master = App.getOfflineUpdatePath("update.spapkg");
				if (master.exists()) {
					Intent intent = new Intent(this, UpdateMasterOfflineActivity.class);
					intent.putExtra("GOTO_MAIN", true);
					startActivity(intent);
				} else if (file.exists()) {
					Intent intent = new Intent(this, UpdateOfflineActivity.class);
					intent.putExtra("GOTO_MAIN", true);
					startActivity(intent);
				}			
			} else if (_goToLoginWhenDone) {
				Intent intent = new Intent(this, LoginActivity.class);				
				startActivity(intent);			
			}
			
			finish();
		}
	}

	private void cancelAll() {
		for (BaseProgressTask task : _list) {
			task.cancel(true);
		}
		
		setAllFinish();
	}

	@Override
	public void onBackPressed() {
		if (_cancelable) {
			if (isAllFinish()) {
				if (_handler != null) _handler.close();
				finish();
				return;				
			}

			new AlertDialog.Builder(new ContextThemeWrapper(this,
					R.style.Theme_Sherlock_Light_Dialog))
					.setIcon(android.R.drawable.ic_dialog_alert)
					.setTitle(R.string.confirm)
					.setMessage("Anda yakin akan membatalkan proses?")
					.setCancelable(false)
					.setPositiveButton(R.string.yes,
							new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog,
										int which) {
									dialog.dismiss();
									cancelAll();
									setAllFinish();
									if (_handler != null) _handler.close();
								}
							}).setNegativeButton(R.string.no, null).show();
		}
	}
	
	@Override
	public void onUserInteraction() {		
		super.onUserInteraction();
		((CustomSessionApplication) getApplication()).touch();
		if (App.DEBUG) {			
			Log.d("User Interaction", "User interaction to "+this.toString());			
		}
	}
}
